using System;
using System.Diagnostics;
using System.Reflection;
using Mbs.Globalization;
using Mbs.Reflection;

namespace Mbs.Modularity
{
    [Serializable]
    internal class ModuleActivatorProcessor : MarshalByRefObject, IModuleActivatorProcessor
    {
        private IModuleActivator activator;
        private bool isAsyn;

        public IServiceLocator Locator { get; set; }
        public IClassLoader ClassLoader { get; set; }

        public ModuleActivatorProcessor(IModuleMeta meta, IClassLoader classLoader)
        {
            ClassLoader = classLoader;
            var asm = classLoader.LoadAssembly(meta.AssemblyFile);

            InitResources(meta,asm);
            InitActivator(GetMouleActivatorType(asm));
        }

        public ModuleActivatorProcessor(IModuleActivator activator, bool isAsyn, IModuleMeta meta)
        {
            this.activator = activator;
            this.isAsyn = isAsyn;
            InitResources(meta, activator.GetType().Assembly);
        }

        private void InitResources(IModuleMeta meta, Assembly asm)
        {
            if (meta.AddIn != null)
            {
                ResourceRepository.StringRegistry.Register(meta.AddIn.StringResources, asm);
                ResourceRepository.ImageRegistry.Register(meta.AddIn.ImageResources, asm);
            }
        }

        public void Process()
        {

            if (activator == null)
            {
                Trace.WriteLine("No activator found");
                return;
            }

            //if (activator.Locator == null)
            //    activator.Locator = Locator;

            if (isAsyn)
            {
                Action handler = activator.Start;
                handler.Post();
                return;
            }

            try
            {
                activator.Start();
            }
            catch (Exception ex)
            {
                ex.RaiseException();
            }
        }

        private void InitActivator(Type activatorType)
        {
            activator = ClassLoader.NewInstance<IModuleActivator>(activatorType);
            //activator.Locator = Locator;

            var attribute = activatorType.GetAttribute<ModuleActivatorAttribute>(true);
            isAsyn = attribute != null && attribute.IsAsyn ? true : false;
        }

        private Type GetMouleActivatorType(Assembly asm)
        {
            var serviceType = typeof(IModuleActivator);
            foreach (var type in asm.GetExportedTypes())
            {
                if (serviceType.IsAssignableFrom(type) && !type.IsAbstract)
                    return type;
            }
            return null;
        }

        public void Dispose()
        {
            //TODO: Unload Resources
            if (activator != null)
                activator.Stop();
        }
    }
}
